#include "stdafx.h"
#include "xSceneGraphWrite.h"
#include "OpenColladaHelp.h"

namespace XE
{


	//------------------------------
	SceneGraphWriter::SceneGraphWriter( xEngineWrite* Writer, \
		const COLLADAFW::VisualScene& visualScene, \
		const xEngineWrite::LibraryNodesList& libraryNodesList,xSceneManager* pxSceneMgr )
		: xBaseWrite( Writer )
		, mVisualScene(visualScene)
		, mLibraryNodesList(libraryNodesList)
		,m_pSceneMrg(pxSceneMgr)

	{
	}

	//------------------------------
	SceneGraphWriter::~SceneGraphWriter()
	{
	}

	//------------------------------
	bool SceneGraphWriter::write(  )
	{
		createUniqueIdNodeMap();

		NodeInfo nodeInfo( COLLADABU::Math::Matrix4::IDENTITY );
		mNodeInfoStack.push( nodeInfo );

		writeNodes( mVisualScene.getRootNodes());
		return true;
	}

	//------------------------------
	bool SceneGraphWriter::writeNodes( const COLLADAFW::NodePointerArray& nodesToWriter )
	{
		for ( size_t i = 0, count = nodesToWriter.getCount(); i < count; ++i)
		{
			writeNode(nodesToWriter[i]);
		}
		return true;
	}

	//------------------------------
	bool SceneGraphWriter::writeNode(const COLLADAFW::Node* nodeToWriter )
	{

		const NodeInfo& parentNodeInfo = mNodeInfoStack.top();
		const COLLADABU::Math::Matrix4& parentWorldMatrix = parentNodeInfo.worldTransformation;
		COLLADABU::Math::Matrix4 worldMatrix = parentWorldMatrix * nodeToWriter->getTransformationMatrix();
		NodeInfo nodeInfo( worldMatrix );
		mNodeInfoStack.push(nodeInfo);

		writeNodes(nodeToWriter->getChildNodes());

        xString nodeName =  nodeToWriter->getName();
		storeInstanceGeometries( nodeToWriter->getInstanceGeometries(), worldMatrix,nodeName);

		writeInstanceNodes( nodeToWriter->getInstanceNodes() );

		mNodeInfoStack.pop();

		return true;
	}


	//------------------------------
	void SceneGraphWriter::storeInstanceGeometries( const COLLADAFW::InstanceGeometryPointerArray& instanceGeometries, 
		const COLLADABU::Math::Matrix4& worldMatrix ,const xString& name )
	{
		for ( size_t i = 0, count = instanceGeometries.getCount(); i < count; ++i)
		{
			COLLADAFW::InstanceGeometry* instanceGeometry = instanceGeometries[i];
			xEngineWrite::InstanceGeometryInfo instanceGeometryInfo( instanceGeometry, worldMatrix ,name);
			addGeometryUniqueIdInstanceGeometryInfoPair(instanceGeometry->getInstanciatedObjectId(), instanceGeometryInfo);
		}
	}

	//------------------------------
	void SceneGraphWriter::writeInstanceNodes( const COLLADAFW::InstanceNodePointerArray& instanceNodes)
	{
		for ( size_t i = 0, count = instanceNodes.getCount(); i < count; ++i)
		{
			const COLLADAFW::InstanceNode* instanceNode = instanceNodes[i];
			const COLLADAFW::UniqueId& referencedNodeUniqueId = instanceNode->getInstanciatedObjectId();
			UniqueIdNodeMap::const_iterator it = mUniqueIdNodeMap.find( referencedNodeUniqueId );
			if ( it != mUniqueIdNodeMap.end() )
			{
				const COLLADAFW::Node* referencedNode = it->second;
				writeNode( referencedNode );
			}
		}
	}

	//------------------------------
	void SceneGraphWriter::createUniqueIdNodeMap( COLLADAFW::Node* node ,const COLLADAFW::Node* pParaent)
	{
		if(m_pSceneMrg->GetSceneNodeByName(node->getName())==NULL)
		{
			xSceneNode* pSecenNode=NULL;
			if(pParaent==NULL)
			{
				pSecenNode=m_pSceneMrg->CreateSceneNode(node->getName());
			}else
			{
				xSceneNode* pParaent  = m_pSceneMrg->GetSceneNodeByName(pParaent->GetName());
				pSecenNode =  m_pSceneMrg->CreateSceneNode(node->getName(),pParaent);
			
			}
			COLLADABU::Math::Matrix4  ColladaMatrix  = node->getTransformationMatrix();
			xMatrix loacl;
			OpenColladaHelp::OpenColladaMatrixToxMatrix(loacl,ColladaMatrix);
			pSecenNode->SetLocalMatrix(loacl);


		}


		mUniqueIdNodeMap[node->getUniqueId()] = node;
		createUniqueIdNodeMap( node->getChildNodes() );
	}

	//------------------------------
	void SceneGraphWriter::createUniqueIdNodeMap( const COLLADAFW::NodePointerArray& nodes,const COLLADAFW::Node* pParaent )
	{
		for ( size_t i = 0, cout = nodes.getCount(); i < cout; ++i)
		{
			COLLADAFW::Node* node = nodes[i];
			createUniqueIdNodeMap( node ,pParaent);
		}
	}

	//------------------------------
	void SceneGraphWriter::createUniqueIdNodeMap()
	{
		createUniqueIdNodeMap( mVisualScene.getRootNodes() );
		xEngineWrite::LibraryNodesList::const_iterator it = mLibraryNodesList.begin();
		for ( ; it != mLibraryNodesList.end(); ++it )
		{
			const COLLADAFW::LibraryNodes& libraryNodes = *it;
			createUniqueIdNodeMap( libraryNodes.getNodes() );
		}
	}

}